package com.zhiche.wms.service.sys.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.wms.configuration.MyConfigurationProperties;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.InterfaceAddrEnum;
import com.zhiche.wms.core.supports.enums.SysSourceEnum;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.Account.AccountUtil;
import com.zhiche.wms.core.utils.Account.JwtAccountVO;
import com.zhiche.wms.core.utils.HttpRequestUtil;
import com.zhiche.wms.domain.mapper.sys.UserMapper;
import com.zhiche.wms.domain.model.base.Storehouse;
import com.zhiche.wms.domain.model.opbaas.OpDeliveryPoint;
import com.zhiche.wms.domain.model.sys.User;
import com.zhiche.wms.domain.model.sys.UserDeliveryPoint;
import com.zhiche.wms.domain.model.sys.UserRole;
import com.zhiche.wms.domain.model.sys.UserStorehouse;
import com.zhiche.wms.service.base.IStorehouseService;
import com.zhiche.wms.service.constant.SourceSystem;
import com.zhiche.wms.service.sys.IUserDeliveryPointService;
import com.zhiche.wms.service.sys.IUserRoleService;
import com.zhiche.wms.service.sys.IUserService;
import com.zhiche.wms.service.sys.IUserStorehouseService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author zhaoguixin
 * @since 2018-06-19
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private MyConfigurationProperties properties;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IUserDeliveryPointService userDeliveryPointService;
    @Autowired
    private IUserStorehouseService userStorehouseService;
    @Autowired
    private IStorehouseService storehouseService;
    @Autowired
    private IUserService userService;

    @Override
    public void saveUser(Map<String, Object> param, String authorization) {
        if (param == null || param.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        User loginUser = getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");

        }
        Object code = param.get("code");
        Object name = param.get("name");
        Object mobile = param.get("mobile");
        Object password = param.get("password");
        Object email = param.get("email");
        Object houseId = param.get("houseId");
        if (code == null || StringUtils.isBlank(code.toString().trim())) {
            throw new BaseException("编码不能为空");
        }
        if (name == null || StringUtils.isBlank(name.toString().trim())) {
            throw new BaseException("姓名不能为空");
        }
        if (mobile == null || StringUtils.isBlank(mobile.toString().trim())) {
            throw new BaseException("手机号不能为空");
        }
        if (password == null || StringUtils.isBlank(password.toString().trim())) {
            throw new BaseException("密码不能为空");
        }
        if (houseId == null || StringUtils.isBlank(houseId.toString().trim())) {
            throw new BaseException("仓库不能为空");
        }
        String mb = mobile.toString().trim();
        String cd = code.toString().trim();
        String ne = name.toString().trim();
        String pd = password.toString().trim();
        String em = (email == null || StringUtils.isBlank(email.toString().trim())) ?
                null : email.toString().trim();

        EntityWrapper<User> ew = new EntityWrapper<>();
        ew.eq("mobile", mobile)
                .eq("status", TableStatusEnum.STATUS_1.getCode());
        Integer count = this.baseMapper.selectCount(ew);
        if (count > 0) {
            throw new BaseException("用户手机:" + mobile + "已经注册,请登录");
        }
        //注册
        Map<String, Object> registerMap = Maps.newHashMap();
        registerMap.put("mobile", mb);
        registerMap.put("mail", em);
        registerMap.put("password", pd);
        registerMap.put("tenantId", 1);
        Map<String, Object> header = Maps.newHashMap();
        header.put("Authorization", authorization);
        String uaaResult = null;

        try {
            uaaResult = HttpRequestUtil.sendPostJSON(properties.getUaahost() + InterfaceAddrEnum.UAA_SIGNUP_NORMAL.getAddress(),
                    properties.getSocketTimeOut(),
                    registerMap, header);
        } catch (Exception e) {
            logger.error("register server error: {}", e);
            throw new BaseException("连接认证服务器超时");
        }
        if (StringUtils.isBlank(uaaResult)) {
            throw new BaseException("连接认证服务器失败");
        }
        JSONObject jsonObject = JSONObject.parseObject(uaaResult);
        Integer resultCode = jsonObject.getInteger("code");
        if (resultCode != 0) {
            throw new BaseException("注册UAA失败:" + jsonObject.getString("message"));
        }
        insertUserAndStoreUser(param, loginUser, mb, cd, ne, em);
    }


    /**
     * 分页查询用户
     */
    @Override
    public Page<User> selectUserPage(Page<User> page) {
        if (page == null) {
            throw new BaseException("参数不能为空");
        }
        Map<String, Object> cd = page.getCondition();
        EntityWrapper<User> ew = new EntityWrapper<>();
        if (cd != null) {
            if (Objects.nonNull(cd.get("name")) && StringUtils.isNotBlank(cd.get("name").toString())) {
                ew.like("name", cd.get("name").toString().trim());
            }
            if (Objects.nonNull(cd.get("code")) && StringUtils.isNotBlank(cd.get("code").toString())) {
                ew.eq("code", cd.get("code").toString().trim());
            }
            if (Objects.nonNull(cd.get("mobile")) && StringUtils.isNotBlank(cd.get("mobile").toString())) {
                ew.like("mobile", cd.get("mobile").toString().trim());
            }
            if (Objects.nonNull(cd.get("status")) && StringUtils.isNotBlank(cd.get("status").toString())) {
                ew.eq("status", cd.get("status").toString().trim());
            }
            if (Objects.nonNull(cd.get("gender")) && StringUtils.isNotBlank(cd.get("gender").toString())) {
                ew.eq("gender", cd.get("gender").toString().trim());
            }
            if (Objects.nonNull(cd.get("email")) && StringUtils.isNotBlank(cd.get("email").toString())) {
                ew.eq("email", cd.get("email").toString().trim());
            }
            if (Objects.nonNull(cd.get("roleName")) && StringUtils.isNotBlank(cd.get("roleName").toString())) {
                ew.like("roleName", cd.get("roleName").toString().trim());
            }
            if (Objects.nonNull(cd.get("deliveryCode")) && StringUtils.isNotBlank(cd.get("deliveryCode").toString())) {
                ew.like("deliveryCode", cd.get("deliveryCode").toString().trim());
            }
            if (Objects.nonNull(cd.get("storeCode")) && StringUtils.isNotBlank(cd.get("storeCode").toString())) {
                ew.like("storeCode", cd.get("storeCode").toString().trim());
            }
        }
        List<User> list = baseMapper.selectUserPage(page, ew);
        return page.setRecords(list);
    }

    /**
     * 修改用户密码
     */
    @Override
    public String updatePwd(Map<String, Object> param, String authorization) {
        User loginUser = getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请先登录");
        }
        if (param == null || param.isEmpty()) {
            throw new BaseException("传入参数不能为空");
        }
        Object npwd = param.get("newPassword");
        Object oldPassword = param.get("oldPassword");
        if (npwd == null || StringUtils.isBlank(npwd.toString())) {
            throw new BaseException("新密码不能为空");
        }
        if (oldPassword == null || StringUtils.isBlank(oldPassword.toString())) {
            throw new BaseException("旧密码不能为空");
        }

        // 修改密码
        JwtAccountVO info = AccountUtil.getAccountInfoFromSecurityContext();
        Map<String, Object> updateMap = Maps.newHashMap();
        updateMap.put("accountId", info.getAccountId());
        updateMap.put("oldPassword", oldPassword.toString());
        updateMap.put("password", npwd.toString());
        HashMap<String, Object> header = Maps.newHashMap();
        header.put("Authorization", authorization);
        String uaaResult = null;
        try {
            uaaResult = HttpRequestUtil.sendHttpPost(properties.getUaahost() + InterfaceAddrEnum.UAA_UPDATE_PASSWORD.getAddress(),
                    header, updateMap, properties.getSocketTimeOut());
        } catch (Exception e) {
            logger.error("register server error: {}", e);
            throw new BaseException("修改密码失败");
        }
        if (StringUtils.isBlank(uaaResult)) {
            throw new BaseException("连接认证服务器失败!");
        }
        JSONObject jsonObject = JSONObject.parseObject(uaaResult);
        Integer code = jsonObject.getInteger("code");
        if (code == 0) {
            return uaaResult;
        } else {
            throw new BaseException("修改密码失败:" + jsonObject.getString("message"));
        }

    }

    @Override
    public void disableUserInfo (Map<String, Object> param) {
        List<String> userIds = (List<String>) param.get("userIds");
        if (CollectionUtils.isEmpty(userIds)) {
            throw new BaseException("禁用用户信息的条件【userIds】不能为空");
        }
        //1标识有效，0表示禁用
        String type = (String) param.get("type");
        if (StringUtils.isEmpty(type)) {
            throw new BaseException("禁用用户信息的条件【type】不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("未查询到登录用户");
        }
        String remark = "";
        if (TableStatusEnum.STATUS_0.getCode().equals(type)) {
            if (StringUtils.isEmpty((String) param.get("remark"))) {
                throw new BaseException("禁用用户备注不能为空！");
            }
            remark = (String) param.get("remark");
        }
        User user = new User();
        user.setStatus(Integer.valueOf(type));
        user.setGmtModified(new Date());
        user.setModifiedUser(loginUser.getName());
        user.setRemark(remark);
        EntityWrapper<User> entityWrapper = new EntityWrapper<>();
        entityWrapper.in("id", userIds);
        baseMapper.update(user, entityWrapper);
    }

    @Override
    public User queryLoginUser (String genMethod) {
        User loginUser = null;
        if (SourceSystem.AUTO.equals(genMethod)) {
            loginUser = new User();
            loginUser.setName(SysSourceEnum.AUTO.getName());
            loginUser.setCode(SysSourceEnum.AUTO.getCode());
        } else if (SourceSystem.HONEYWELL.equals(genMethod)) {
            loginUser = new User();
            loginUser.setName(SysSourceEnum.HONEYWELL.getName());
            loginUser.setCode(SysSourceEnum.HONEYWELL.getCode());
        } else {
            loginUser = userService.getLoginUser();
        }
        return loginUser;
    }

    @Override
    public int assignRole(Integer userId, List<Integer> roleIds) {
        if (Objects.equals(userId, null)) {
            logger.error("UserServiceImpl.assignRole param uid must not be null ");
            throw new IllegalArgumentException("用户id不能为空");
        }

        //查询角色数据库中的角色
        EntityWrapper<UserRole> ew = new EntityWrapper<>();
        ew.eq("user_id", userId);
        List<UserRole> dbUserRoles = userRoleService.selectList(ew);

        List<Integer> dbRoleIds = new ArrayList<>();
        dbUserRoles.forEach(userRole -> dbRoleIds.add(userRole.getRoleId()));

        authorize(userId, roleIds, dbRoleIds);
        return 1;
    }

    @Override
    public List<UserRole> listUserRole(Integer userId) {
        EntityWrapper<UserRole> ew = new EntityWrapper<>();
        ew.eq("user_id", userId);
        return userRoleService.selectList(ew);
    }

    @Override
    public User getLoginUser() throws BaseException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (Objects.isNull(authentication)) throw new BaseException("无认证账号信息，请先认证！");
        String loginTicket = authentication.getPrincipal().toString();
        Wrapper<User> ew = new EntityWrapper<>();
        ew.eq("mobile", loginTicket)
                .or().eq("email", loginTicket);
        User user = selectOne(ew);
        if (Objects.isNull(user)) throw new BaseException("用户不存在！");
        if(TableStatusEnum.STATUS_0.getCode().equals(String.valueOf(user.getStatus()))){
            throw new BaseException("此用户已被禁用，请联系系统管理员！");
        }
        return user;
    }

    @Override
    public List<Storehouse> listUserStorehouse(Integer userId) {
        return baseMapper.listUserStorehouse(userId);
    }

    @Override
    public int assignHouse(Integer userId, List<Long> houseIds) throws Exception {
        if (Objects.equals(userId, null)) {
            logger.error("UserServiceImpl.assignHouse param uid must not be null ");
            throw new IllegalArgumentException("用户id不能为空");
        }

        //查询角色数据库中的角色
        EntityWrapper<UserStorehouse> ew = new EntityWrapper<>();
        ew.eq("user_id", userId);
        List<UserStorehouse> dbUserHouses = userStorehouseService.selectList(ew);

        List<Long> dbHosueIds = new ArrayList<>();
        dbUserHouses.forEach(userHosue -> dbHosueIds.add(userHosue.getStoreHouseId()));

        authorizeHouse(userId, houseIds, dbHosueIds);
        return 1;
    }

    @Override
    public List<OpDeliveryPoint> listUserDeliveryPoint(Integer userId) {
        Wrapper<OpDeliveryPoint> ew = new EntityWrapper<>();
        ew.eq("a.user_id", userId)
                .eq("a.status", TableStatusEnum.STATUS_10.getCode())
                .orderBy("a.point_id", false);
        return baseMapper.listOwnPointPrival(ew);
    }

    @Override
    public int assignPoint(Integer userId, List<OpDeliveryPoint> points) {
        User loginUser = getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登录后进行该操作");
        }

        if (Objects.equals(userId, null)) {
            logger.error("UserServiceImpl.assignHouse param uid must not be null ");
            throw new IllegalArgumentException("用户id不能为空");
        }

        //查询角色数据库中的角色
        EntityWrapper<UserDeliveryPoint> ew = new EntityWrapper<>();
        ew.eq("user_id", userId);
        List<UserDeliveryPoint> dbUserPoint = userDeliveryPointService.selectList(ew);

        List<Long> dbPointIds = new ArrayList<>();
        dbUserPoint.forEach(userDeliveryPoint -> dbPointIds.add(userDeliveryPoint.getPointId()));

        authorizePoint(userId, points, loginUser);
        return 1;
    }

    /**
     * 获取用户仓库列表
     */
    @Override
    public List<Storehouse> getHousesListByToken() {
        User loginUser = getLoginUser();
        if (loginUser != null) {
            EntityWrapper<UserStorehouse> ew = new EntityWrapper<>();
            ew.eq("user_id", loginUser.getId());
            List<UserStorehouse> storehouses = userStorehouseService.selectList(ew);
            if (CollectionUtils.isNotEmpty(storehouses)) {
                ArrayList<Long> hIds = Lists.newArrayList();
                for (UserStorehouse sh : storehouses) {
                    hIds.add(sh.getStoreHouseId());
                }
                return storehouseService.selectBatchIds(hIds);
            }
        }
        return null;
    }

    private void insertUserAndStoreUser(Map<String, Object> param, User loginUser, String mb, String cd, String ne, String em) {
        User user = new User();
        user.setCode(cd);
        user.setName(ne);
        user.setMobile(mb);
        user.setEmail(em);
        user.setDepartment((param.get("department") == null || StringUtils.isBlank(param.get("department").toString().trim())) ?
                null : param.get("department").toString().trim());
        user.setGender((param.get("gender") == null || StringUtils.isBlank(param.get("gender").toString().trim())) ?
                null : Integer.valueOf(param.get("gender").toString().trim()));
        user.setCreateUser(loginUser.getName());
        user.setModifiedUser(loginUser.getName());
        user.setStatus(Integer.valueOf(TableStatusEnum.STATUS_1.getCode()));
        insert(user);
        EntityWrapper<User> ew1 = new EntityWrapper<>();
        ew1.eq("mobile", mb)
                .eq("status", TableStatusEnum.STATUS_1.getCode());
        List<User> users = selectList(ew1);
        UserStorehouse userStorehouse = new UserStorehouse();
        userStorehouse.setUserId(users.get(0).getId());
        userStorehouse.setStoreHouseId(Long.valueOf(param.get("houseId").toString().trim()));
        userStorehouseService.insert(userStorehouse);
    }

    private void authorize(Integer userId, List<Integer> assignRoleIds, List<Integer> dbRoleIds) {
        //循环删除数据库有，但指派权限中不包含的权限
        for (Integer roleId : dbRoleIds) {
            if (!contain(roleId, assignRoleIds)) {
                EntityWrapper<UserRole> ew = new EntityWrapper<>();
                ew.eq("user_id", userId).eq("role_id", roleId);
                userRoleService.delete(ew);
            }
        }

        //循环增加指派权限中有，但数据库中不包含的权限
        for (Integer roleId : assignRoleIds) {
            if (!contain(roleId, dbRoleIds)) {
                UserRole userRole = new UserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                userRoleService.insert(userRole);
            }
        }
    }

    private void authorizeHouse(Integer userId, List<Long> assignHouseIds, List<Long> dbHouseIds) {
        //循环删除数据库有，但指派权限中不包含的仓库权限
        for (Long houseId : dbHouseIds) {
            if (!containLong(houseId, assignHouseIds)) {
                EntityWrapper<UserStorehouse> ew = new EntityWrapper<>();
                ew.eq("user_id", userId).eq("store_house_id", houseId);
                userStorehouseService.delete(ew);
            }
        }

        //循环增加指派权限中有，但数据库中不包含的仓库权限
        for (Long houseId : assignHouseIds) {
            if (!containLong(houseId, dbHouseIds)) {
                UserStorehouse userStorehouse = new UserStorehouse();
                userStorehouse.setUserId(userId);
                userStorehouse.setStoreHouseId(houseId);
                userStorehouseService.insert(userStorehouse);
            }
        }
    }

    private void authorizePoint(Integer userId, List<OpDeliveryPoint> assignPoints, User loginUser) {
        //循环删除数据库已有的仓库权限配置
        EntityWrapper<UserDeliveryPoint> ew = new EntityWrapper<>();
        ew.eq("user_id", userId);
        userDeliveryPointService.delete(ew);

        //循环增加仓库权限配置
        for (OpDeliveryPoint point : assignPoints) {
            UserDeliveryPoint userDeliveryPoint = new UserDeliveryPoint();
            userDeliveryPoint.setUserId(userId);
            userDeliveryPoint.setPointId(Long.valueOf(point.getId()));
            userDeliveryPoint.setIsSeek(point.getIsSeekChecked() ? 1 : 0);
            userDeliveryPoint.setIsMove(point.getIsMoveChecked() ? 1 : 0);
            userDeliveryPoint.setIsPick(point.getIsPickChecked() ? 1 : 0);
            userDeliveryPoint.setIsShip(point.getIsShipChecked() ? "1" : "0");
            userDeliveryPoint.setUserCreate(loginUser.getName());
            userDeliveryPoint.setUserModified(loginUser.getName());
            userDeliveryPoint.setGmtCreate(new Date());
            userDeliveryPoint.setGmtModified(new Date());
            userDeliveryPointService.insert(userDeliveryPoint);
        }
    }

    private boolean contain(Integer aim, List<Integer> collection) {
        for (Integer i : collection) {
            if (aim.equals(i)) return true;
        }
        return false;
    }

    private boolean containLong(Long aim, List<Long> collection) {
        for (Long i : collection) {
            if (aim.equals(i)) return true;
        }
        return false;
    }

}
